ここでは、他の回で採り上げなかったC++(C++98)とC言語(C99)の細かなちがいについて解説します。
可変個の実引数を取る関数の仮引数並び
C++では、printf関数のような可変個の実引数を受け取る関数の仮引数並びを次のように記述することができました。
0 1 2 |
int printf(const char* format ...); /* エラー */ |
しかし、C言語では、必ず…の前にコンマを記述する必要があります。
0 1 2 |
int printf(const char* format, ...); /* OK */ |
言語結合は使えない
C++では、extern “C”やextern “C++”のような「言語結合」を指定することができました。しかし、C99にはこのような機能はありません。他言語のコーリングコンベンションにあわせるには、__pascalや__fortranのような独自拡張のキーワードを使うことが多いようです。
使用できる識別子
識別子に関しては、C++に比べてC99のほうが制約がゆるいこともあれば、逆に制約が厳しいこともあります。
識別子途中の二重下線
C++では、識別の先頭だけでなく、途中や末尾にも二重の下線が含まれていてはいけません(予約名になります)。しかし、C99では、先頭の二重下線は予約済み識別子になりますが、それ以外の場所に二重下線が含まれていても問題ありません。ただし、C++と共通で使用するヘッダファイルでは、C99ではよくてもC++ではダメですので、途中や末尾に二重下線を含む識別子を使ってはいけません。
C++のキーワード
C99にはないC++だけのキーワードは、C99では識別子として使うことができます。ただ、無用の混乱を招くおそれがありますので、そうした識別子の使用は避けたほうがよいでしょう。
bool, true, false, and, or, notなどの識別子は、C99では
C99特有のキーワード
C99では、C90に対して、キーワードがいくつか追加されています。_Bool, _Complex, _Imaginary, _Pragma, inline, restrictがそうです。inlineはC++でもありますが、restrictはC++にはないキーワードなので要注意です。下線で始まるキーワードについては、C++では予約済み識別子ですので、もともと一般識別子としては使えなかったものですから、(正しい知識があるC++プログラマにとっては)問題になることはないでしょう。
識別子の有意文字数
C++では、内部および外部識別子の有意文字数としては1024文字まで保証されます。しかし、C99ではずっと制約が厳しく、内部識別子は 63 文字、外部識別子は31文字までです。内部識別子については、国際文字名でも1文字は1文字ですが、外部識別子の場合、\uFFFF以下の国際文字名は6文字、それ以外の国際文字名は10文字に数えられます。結果として、通常の日本語の外部識別子は5文字までしか保証されないことになります。
国際文字名
C++と同様、C99でも識別子に国際文字名を使うことができます。ただし、ソースコード上の多バイト文字が国際文字名に変換されることは、C++ほど明確に規定されているわけではありません。
代替字句
C++では、and, or, not, bitand, and_eqや、<%, %:などの代替字句を使うことができます。しかし、C99では、andやorのような代替字句はマクロとして<iso646.h>ヘッダで定義されます。また、<%や%:などの代替字句は二文字表記と呼ばれ、そのまま使うことができます。
条件演算子
C99とC++では、条件演算子の構文が微妙に異なります。具体的には、C++では、
0 1 2 |
logical-or-expression ? expression : assignment-expression |
であるのに対して、C99では、
0 1 2 |
logical-OR-expression ? expression : conditional-expression |
となっています。第3オペランドにコピー代入演算子や複合代入演算子を含む式を指定した場合、解釈が変わるので要注意です。